﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml.Serialization;
using Evolution.Client.ImportData.Infrastructure;

namespace Evolution.Client.ImportData.Mapper
{
    public class ImportDataMapper
    {
        private static List<DataObjectMapping> dataObjects;

        /// <summary>
        /// Get Data Objects need to be processed from SOSDataMapping file
        /// </summary>
        /// <returns></returns>
        public static List<DataObjectMapping> GetDataObjectsMapping()
        {
            if(dataObjects == null)
            {
                var serializer = new XmlSerializer(typeof(List<DataObjectMapping>));
                TextReader textReader = new StreamReader(ImportSettings.GetInstance().MappingFile);
                dataObjects = (List<DataObjectMapping>)serializer.Deserialize(textReader);
                textReader.Close();
            }
            return dataObjects;
        }

        /// <summary>
        /// Initial an object type for serialise data template process. In case this object type contains a collection, 
        /// then an default item will be added to this collection.
        /// </summary>
        /// <param name="objectType"></param>
        /// <returns></returns>
        public static object InitializeDeepHierachyObject(Type objectType)
        {
            var objectInstance = Activator.CreateInstance(objectType);

            PropertyInfo[] properties = objectType.GetProperties();
            Type tColl = typeof(ICollection<>);
            foreach (PropertyInfo pi in properties)
            {
                Type t = pi.PropertyType;
                if (t.IsGenericType && tColl.IsAssignableFrom(t.GetGenericTypeDefinition()) ||
                    t.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == tColl))
                {
                    if (pi.CanWrite && pi.PropertyType.GetGenericArguments().Any())
                    {
                        var pInstance = Activator.CreateInstance(pi.PropertyType.GetGenericArguments()[0]);
                        var list = ImportDataMapper.GetList(pInstance.GetType());
                        list.Add(pInstance);
                        pi.SetValue(objectInstance, list, null);
                    }
                }
            }
            return objectInstance;
        }

        /// <summary>
        /// Initialize an anonymous type list
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static IList GetList(Type type)
        {
            return (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(type));
        }
    }
}
